﻿
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Runtime.InteropServices;
using TCPIPControl.StructHelper;

namespace TcpLabCommon
{
    /// <summary>
    /// 网络封包Tcp服务类
    /// </summary>
    public class Cls_NetPacketTcpService :Cls_NetPacketService 
    {

        public Cls_NetPacketTcpService(NetworkStream netStream) : base(netStream) { }

        /// <summary>
        /// 提取一个完整网络包然后返回
        ///     如果收到的包是STRING类型,NetPacket.Data是发送的字符串
        ///     如果收到的包是BINARY类型,NetPacket.Data是发送的文件名长度+文件名+文件内容,请调用ParseFile函数进行解析
        ///     如果收到的包是COMPLEX类型,NetPacket.Data是发序列化的对象，可以直接转型使用
        /// </summary>
        /// <returns></returns>
        public override NetPacket ReceivePacket()
        {
            #region 【接收Tcp包】

            while (true)
            {
                //判断是否满足一个完整封包大小
                if (IsFullNetPacket())//如果有完整封包就返回
                {
                    return PickNetPacket();
                }

                #region 【缓冲区不满足一个完整封包大小则继续从网络流读取数据】
                int readLen = _netStream.Read(_tempBuffer, 0, BUFFER_SIZE);
                //判断读取的字节数+缓冲区已有字节数是否超过缓冲区总大小
                if (readLen + _netDataOffset > _netDataBuffer.Length)
                {
                    Array.Resize<Byte>(ref _netDataBuffer, _netDataBuffer.Length + BUFFER_SIZE * 2);
                }
                //将新读取的数据拷贝到缓冲区
                Array.Copy(_tempBuffer, 0, _netDataBuffer, _netDataOffset, readLen);
                //修改"网络数据实际长度"
                _netDataOffset += readLen;
                #endregion
            }
            #endregion
        }

        //ACQParametersConfigSerializeHelper 

        /// <summary>
        /// 发包[发送Tcp包/发送Udp数据报]
        /// </summary>
        /// <param name="packet"></param>
        protected override void SendPacket(NetPacket packet)
        {
            if (packet == null || packet.Data == null || packet.PacketHead == null)
                return;
            byte[] buffer = null;
            #region【计算包体长度】
            switch (packet.PacketHead.PType)
            {
                case PacketType.STRING:
                    string a = packet.Data as string;
                    buffer = Serializehelper<StringSerializeHelper>().Serialize(a);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.ACQParametersConfig:
                    ACQParametersConfig acq = (ACQParametersConfig)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(acq);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.AccelerationPacket:
                    AccData acc = (AccData)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(acc);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.DisplacementPacket:
                    DisplacementData dataPacket = (DisplacementData)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(dataPacket);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.SlowSignalPacket:
                    SlowSignal slow = (SlowSignal)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(slow);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.SpeedPacket:
                    SpeedData speed = (SpeedData)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(speed);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.SamplingPacket:
                    SamplingConfig speedreal = (SamplingConfig)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(speedreal);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.TimeSetting:
                    MachineTime machinetime = (MachineTime)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(machinetime);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                case PacketType.TimeUpload:
                    MachineTime machinetime1 = (MachineTime)packet.Data;
                    buffer = Serializehelper<StructHelper>().Serialize(machinetime1);
                    packet.PacketHead.Len = buffer.Length;
                    break;
                default:
                    break;
            }

            #endregion

            #region【写入包头】
            _netStream.Write(BitConverter.GetBytes(packet.PacketHead.Version), 0, Marshal.SizeOf(packet.PacketHead.Version));
            _netStream.Write(BitConverter.GetBytes((Int32)packet.PacketHead.PType), 0, sizeof(Int32));
            _netStream.Write(BitConverter.GetBytes(packet.PacketHead.Len), 0, Marshal.SizeOf(packet.PacketHead.Len));
            #endregion

            #region【写入包体】
           
            //switch (packet.PacketHead.PType)
            //{
            //    case PacketType.STRING:
            //        buffer = Serializehelper<StringSerializeHelper>().Serialize(packet.Data as string);
            //        break;
            //    //case PacketType.:
            //    //    buffer = (byte[])packet.Data;
            //    //    break;
            //    //case PacketType.COMPLEX:
            //    //    MemoryStream m = new MemoryStream();
            //        ////SerializeHelper<BinarySerializeHelper>().Serialize(m, packet.Data);
            //    //    m.Position = 0;
            //    //    buffer = new byte[m.Length];
            //    //    m.Read(buffer, 0, (Int32)m.Length);
            //    //    break;
            //}
            if (buffer != null)
                _netStream.Write(buffer, 0, buffer.Length);
            #endregion
        }
    }
}
